using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using log4net;
using Matriculex.Dominio;
using Matriculex.Dominio.Util;

namespace Matriculex.UI.Controllers
{
    [Autorizex(typeof(Gerente))]
    public class RelatorioController : Controller
    {
        private static readonly ILog Logger = LogManager.GetLogger("LogInFile");
        //
        // GET: /Relatorio/

        public ActionResult Index()
        {
            return RedirectToAction("CursoAberto");
        }

        #region "Relatorio de Curso Aberto"

        public ActionResult CursoAberto(int? filtroCurso)
        {
            var alunos = new List<AlunoAberto>();
            var cursos = new List<CursoAberto>();

            var now = DateTime.Now;
            var trimestre = (now.Month + 2)/3;
            var ciclo = new Ciclo(now.Year, trimestre);
            var oferecimentos = Oferecimento.FindAllByCiclo(ciclo);
            
            if (!filtroCurso.HasValue)
            {
                // obtem todos os alunos
                oferecimentos.ForEach(o => o.Alunos.ForEach(a =>
                                                            {
                                                                if (!alunos.Contains(a))
                                                                    alunos.Add(a);
                                                            }));
                // obtem os cursos
                alunos.ForEach(a =>
                {
                    if (!cursos.Contains(a.Curso))
                    {
                        cursos.Add(a.Curso);
                    }
                });
            }
            else
            {
                // pega os alunos do curso se houver
                var curso = Dominio.CursoAberto.Find(filtroCurso);
                if (curso != null)
                {
                    oferecimentos.ForEach(o =>
                                          {
                                              var alunoAbertos = o.Alunos.Where(a => a.Curso == curso);
                                              alunos.AddRange(alunoAbertos);
                                          });
                }
            }

            ViewData["ciclo"] = ciclo;
            ViewData["cursos"] = new SelectList(cursos, "Id", "Nome");
            ViewData["alunos"] = alunos.ToArray();
            return View();
        }

        [AjaxRequestOnly(HttpVerbs.Get)]
        public ActionResult AlunosCursoAberto(int? cursoId)
        {
            try
            {
                var alunos = new List<AlunoAberto>();

                var now = DateTime.Now;
                var trimestre = (now.Month + 2) / 3;
                var ciclo = new Ciclo(now.Year, trimestre);
                var oferecimentos = Oferecimento.FindAllByCiclo(ciclo);

                if (!cursoId.HasValue)
                {
                    // obtem todos os alunos
                    oferecimentos.ForEach(o => o.Alunos.ForEach(a =>
                    {
                        if (!alunos.Contains(a))
                            alunos.Add(a);
                    }));
                }
                else
                {
                    // pega os alunos do curso se houver
                    var curso = (CursoAberto)Dominio.CursoAberto.Find(cursoId);
                    // obtem todos os alunos
                    oferecimentos.ForEach(o => o.Alunos.ForEach(a =>
                    {
                        if (a.Curso == curso && !alunos.Contains(a))
                            alunos.Add(a);
                    }));
                }

                ViewData["alunos"] = alunos.ToArray();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
            }

            return View();
        }

        #endregion "Relatorio de Curso Aberto"

        #region "Relatorio de Curso Fechado"

        public ActionResult CursoFechado(int? filtroCurso)
        {
            var matriculadosCurso = new Dictionary<CursoFechado, int>();
            var alunos = new List<AlunoFechado>();

            var now = DateTime.Now;
            var trimestre = (now.Month + 2) / 3;
            var ciclo = new Ciclo(now.Year, trimestre);
            var rematriculas = Rematricula.FindAllByCiclo(ciclo);

            if (!filtroCurso.HasValue)
            {
                // pega todos os alunos
                rematriculas.ForEach(r =>
                                     {
                                         alunos.Add(r.Aluno);
                                         var curso = r.Aluno.Curso;
                                         if (!matriculadosCurso.ContainsKey(curso))
                                         {
                                             matriculadosCurso[curso] = 1;
                                         }
                                         else
                                         {
                                             matriculadosCurso[curso]++;
                                         }
                                     });
            }
            else
            {
                // pega os alunos do curso se houver
                var curso = Dominio.CursoFechado.Find(filtroCurso);
                if (curso != null)
                {
                    rematriculas.ForEach(r =>
                    {
                        var c = r.Aluno.Curso;
                        if (!matriculadosCurso.ContainsKey(c))
                        {
                            matriculadosCurso[c] = 1;
                        }
                        else
                        {
                            matriculadosCurso[c]++;
                        }
                        if (c == curso && !alunos.Contains(r.Aluno))
                            alunos.Add(r.Aluno);
                    });
                }
            }

            ViewData["ciclo"] = ciclo;
            ViewData["cursos"] = matriculadosCurso;
            ViewData["cursosFiltro"] = new SelectList(matriculadosCurso.Keys, "Id", "nome");
            ViewData["total_alunos"] = rematriculas.Length;
            ViewData["alunos"] = alunos.ToArray();
            return View();
        }

        [AjaxRequestOnly(HttpVerbs.Get)]
        public ActionResult AlunosCurso(int? cursoId)
        {
            try
            {
                var alunos = new List<AlunoFechado>();
                var now = DateTime.Now;
                var trimestre = (now.Month + 2) / 3;
                var ciclo = new Ciclo(now.Year, trimestre);
                var rematriculas = Rematricula.FindAllByCiclo(ciclo);

                if (!cursoId.HasValue)
                {
                    // pega todos os alunos
                    rematriculas.ForEach(r => alunos.Add(r.Aluno));
                }
                else
                {
                    // pega os alunos do curso se houver
                    var curso = (CursoFechado) Dominio.CursoFechado.Find(cursoId);
                    rematriculas.ForEach(r =>
                                         {
                                             if (r.Aluno.Curso == curso)
                                                 alunos.Add(r.Aluno);
                                         });
                }

                ViewData["alunos"] = alunos.ToArray();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
            }

            return View();
        }

        #endregion "Relatorio de Curso Fechado"

        #region "Relatorio de Disciplinas"

        public ActionResult Disciplinas(int? filtroOferecimento)
        {
            var now = DateTime.Now;
            var trimestre = (now.Month + 2) / 3;
            var ciclo = new Ciclo(now.Year, trimestre);

            var oferecimentos = Oferecimento.FindAllByCiclo(ciclo);
            var alunos = new List<AlunoAberto>();

            if (!filtroOferecimento.HasValue)
            {
                // Obtem todos os alunos
                oferecimentos.ForEach(o => alunos.AddRange(o.Alunos));
            }
            else
            {
                // pega os alunos do oferecimento se houver
                var oferecimento = oferecimentos.ToList().Find(o => o.Id == filtroOferecimento);
                alunos.AddRange(oferecimento.Alunos);
            }

            ViewData["ciclo"] = ciclo;
            ViewData["oferecimentos"] = oferecimentos;
            ViewData["oferecimentosFiltro"] = new SelectList(oferecimentos, "Id", "Disciplina.Nome");
            ViewData["alunos"] = alunos.ToArray();
            return View();
        }

        [AjaxRequestOnly(HttpVerbs.Get)]
        public ActionResult AlunosOferecimento(int? oferecimentoId)
        {
            try
            {
                var alunos = new List<AlunoAberto>();
                if (!oferecimentoId.HasValue)
                {
                    var now = DateTime.Now;
                    var trimestre = (now.Month + 2) / 3;
                    var ciclo = new Ciclo(now.Year, trimestre);
                    Oferecimento.FindAllByCiclo(ciclo)
                        .ForEach(o => alunos.AddRange(o.Alunos));
                }
                else
                {
                    var oferecimento = Oferecimento.Find(oferecimentoId);
                    alunos.AddRange(oferecimento.Alunos);
                }

                ViewData["alunos"] = alunos.ToArray();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
            }

            return View();
        }

        #endregion "Relatorio de Disciplinas"

        #region "Relatorio de Trocas"

        public ActionResult Trocas(int? filtroPeriodo)
        {
            var now = DateTime.Now;
            var trimestre = (now.Month + 2) / 3;
            var ciclo = new Ciclo(now.Year, trimestre);

            var periodos = PeriodoRematricula.FindAllDescByCiclo();
            var periodoVigente = PeriodoRematricula.GetPeriodoByCiclo(ciclo);

            TrocaDisciplina[] trocas = null;

            if (!filtroPeriodo.HasValue)
            {
                trocas = TrocaDisciplina.FindAllByPeriodo(periodoVigente);
            }
            else
            {
                var periodo = periodos.ToList().Find(p => p.Id == filtroPeriodo);
                if (periodo != null)
                {
                    trocas = TrocaDisciplina.FindAllByPeriodo(periodo);
                }
            }
            ViewData["ciclo"] = ciclo;
            ViewData["periodos"] = new SelectList(periodos, "Id", null, periodoVigente.Id);
            ViewData["trocas"] = trocas;
            return View();
        }

        [AjaxRequestOnly(HttpVerbs.Get)]
        public ActionResult TrocasOferecimentos(int? periodoId)
        {
            try
            {
                if (!periodoId.HasValue)
                {
                    var now = DateTime.Now;
                    var trimestre = (now.Month + 2) / 3;
                    var ciclo = new Ciclo(now.Year, trimestre);

                    var periodoVigente = PeriodoRematricula.GetPeriodoByCiclo(ciclo);
                    ViewData["trocas"] = TrocaDisciplina.FindAllByPeriodo(periodoVigente);
                }
                else
                {
                    var periodo = PeriodoRematricula.Find(periodoId);
                    ViewData["trocas"] = TrocaDisciplina.FindAllByPeriodo(periodo);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
            }
            return View();
        }

        #endregion "Relatorio de Trocas"

        #region "Relatorio de Bolsistas"

        /*
        public ActionResult Bolsistas(int? filtroCurso)
        {
            var alunosSet = new HashSet<Aluno>();
            var now = DateTime.Now;
            var trimestre = (now.Month + 2) / 3;
            var ciclo = new Ciclo(now.Year, trimestre);

            // obtenho todos os alunos abertos
            var oferecimentos = Oferecimento.FindAllByCiclo(ciclo);
            oferecimentos.ForEach(o => o.Alunos
                .Where(a => a.Bolsista)
                .ForEach(a => alunosSet.Add(a)));

            // obtenho todos os alunos fechados
            var rematriculas = Rematricula.FindAllByCiclo(ciclo);
            rematriculas.ForEach(r =>
                                 {
                                     if (r.Aluno.Bolsista) alunosSet.Add(r.Aluno);
                                 });

            var alunos = alunosSet.AsEnumerable();
            var cursos = alunos.Select(a => a.GetCurso()).Distinct();

            if (filtroCurso.HasValue)
            {
                var curso = cursos.ToList().Find(c => c.Id == filtroCurso);
                alunos = alunos.Where(a => a.GetCurso() == curso);
            }

            ViewData["ciclo"] = ciclo;
            ViewData["cursos"] = cursos;
            ViewData["cursosFiltro"] = new SelectList(cursos, "Id", "Nome");
            ViewData["total_alunos"] = alunos.Count();
            ViewData["alunos"] = alunos.ToArray();

            return View();
        }

        [AjaxRequestOnly(HttpVerbs.Get)]
        public ActionResult AlunosBolsistas(int? cursoId)
        {
            try
            {
                var alunosSet = new HashSet<Aluno>();
                var now = DateTime.Now;
                var trimestre = (now.Month + 2) / 3;
                var ciclo = new Ciclo(now.Year, trimestre);

                // obtenho todos os alunos abertos
                var oferecimentos = Oferecimento.FindAllByCiclo(ciclo);
                oferecimentos.ForEach(o => o.Alunos
                    .Where(a => a.Bolsista)
                    .ForEach(a => alunosSet.Add(a)));

                // obtenho todos os alunos fechados
                var rematriculas = Rematricula.FindAllByCiclo(ciclo);
                rematriculas.ForEach(r =>
                {
                    if (r.Aluno.Bolsista) alunosSet.Add(r.Aluno);
                });

                var alunos = alunosSet.AsEnumerable();
                if (cursoId.HasValue)
                {
                    var curso = Curso.Find(cursoId);
                    alunos = alunos.Where(a => a.GetCurso() == curso);
                }

                ViewData["alunos"] = alunos.ToArray();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
            }

            return View();
        }
        */

        public ActionResult Bolsistas(int? filtroCurso)
        {
            var cursos = Curso.FindAll();
            var alunos = new List<Aluno>();

            int totalBolsistas;
            if (!filtroCurso.HasValue)
            {
                cursos.ForEach(c =>
                {
                    var bolsistas = c.GetAlunos().Where(a => a.Bolsista);
                    alunos.AddRange(bolsistas);
                });
                totalBolsistas = alunos.Count;
            }
            else
            {
                var curso = cursos.ToList().Find(c => c.Id == filtroCurso);
                var bolsistas = curso.GetAlunos().Where(a => a.Bolsista);
                alunos.AddRange(bolsistas);

                totalBolsistas = cursos.Sum(c =>
                        c.GetAlunos().Where(a => a.Bolsista).Count());
            }

            ViewData["cursos"] = cursos;
            ViewData["cursosFiltro"] = new SelectList(cursos, "Id", "Nome");
            ViewData["total_alunos"] = totalBolsistas;
            ViewData["alunos"] = alunos.ToArray();

            return View();
        }

        [AjaxRequestOnly(HttpVerbs.Get)]
        public ActionResult AlunosBolsistas(int? cursoId)
        {
            var alunos = new List<Aluno>();
            try
            {
                if (!cursoId.HasValue)
                {
                    Curso.FindAll()
                        .ForEach(c =>
                        {
                            var bolsistas = c.GetAlunos().Where(a => a.Bolsista);
                            alunos.AddRange(bolsistas);
                        });
                }
                else
                {
                    var curso = Curso.Find(cursoId);
                    alunos.AddRange(curso.GetAlunos().Where(a => a.Bolsista));
                }

                ViewData["alunos"] = alunos.ToArray();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
            }

            return View();
        }

        #endregion "Relatorio de Bolsistas"
    }
}
